package com.example.shardingsphere.common.config;

import lombok.Data;

import java.util.HashMap;
import java.util.Map;

/**
 * 用户上下文持有者，基于ThreadLocal实现线程安全的用户信息存储
 */
public class UserContextHolder {
    // 使用ThreadLocal存储用户信息，确保线程隔离
    private static final ThreadLocal<UserInfo> userThreadLocal  = new ThreadLocal<>();

    /**
     * 设置当前线程的用户信息
     * @param userInfo 用户信息对象
     */
    public static void setUser(UserInfo userInfo) {
        if (userInfo == null) {
            throw new IllegalArgumentException("用户信息不能为null");
        }
        userThreadLocal.set(userInfo);
    }

    /**
     * 获取当前线程的用户信息
     * @return 用户信息对象
     */
    public static UserInfo getUser() {
        return userThreadLocal.get();
    }

    /**
     * 获取当前用户ID（快捷方法）
     * @return 用户ID
     * @throws IllegalStateException 如果用户未登录
     */
    public static Long getCurrentUserId() {
        UserInfo userInfo = getUser();
        if (userInfo == null || userInfo.getUserId() == null) {
            throw new IllegalStateException("无法获取当前用户ID：用户未登录或上下文信息丢失");
        }
        return userInfo.getUserId();
    }

    /**
     * 获取当前用户角色（快捷方法）
     * @return 用户角色
     * @throws IllegalStateException 如果用户未登录
     */
    public static String getCurrentUserRole() {
        UserInfo userInfo = getUser();
        if (userInfo == null || userInfo.getRole() == null) {
            throw new IllegalStateException("无法获取当前用户角色：用户未登录或上下文信息丢失");
        }
        return userInfo.getRole();
    }

    /**
     * 清除当前线程的用户信息
     * 重要：必须在请求处理完成后调用，防止内存泄漏
     */
    public static void clear() {
        userThreadLocal.remove();
    }


    @Data
    public static class UserInfo{
        // 用户唯一标识
        private Long userId;

        // 用户角色
        private String role;

        // 其他自定义属性
        private Map<String, Object> attributes;

        /**
         * 添加自定义属性
         * @param key 属性键
         * @param value 属性值
         */
        public void addAttribute(String key, Object value) {
            if (attributes == null) {
                attributes = new HashMap<>();
            }
            attributes.put(key, value);
        }

        /**
         * 获取自定义属性
         * @param key 属性键
         * @return 属性值
         */
        public Object getAttribute(String key) {
            return attributes != null ? attributes.get(key) : null;
        }
    }
}
